﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LimitedScopeTrader.Business;
using LimitedScopeTrader.Data;
using LimitedScopeTrader.Data.StocksDataSetTableAdapters;


namespace LimitedScopeTrader
{
    public partial class frmMain : LSTFormBase
    {

        private WSounds Playah;

        public TabControl mainTab;
        /// <summary>
        /// Shows a system error message box.
        /// </summary>
        /// <param name="msg"></param>
        private void ShowErrorMessage(string msg)
        {
            PlayErrorSound();
            MessageBox.Show(msg, ApplicationConstants.MSGBOX_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        private void PlayErrorSound()
        {
            Playah.Play("UhOh.wav", Playah.SND_FILENAME | Playah.SND_ASYNC);
        }

        /// <summary>
        /// Shows a system message indicating a successful operation
        /// </summary>
        /// <param name="msg"></param>
        private void ShowSuccessMessage(string msg)
        {
            MessageBox.Show(msg, ApplicationConstants.MSGBOX_TITLE, MessageBoxButtons.OK, MessageBoxIcon.None);
        }

        /// <summary>
        /// form constructor
        /// </summary>
        public frmMain()
        {
            InitializeComponent();
            this.Playah = new WSounds();
            this.mainTab = this.tabMain;

            businessLayer = new LimitedScopeBusiness();
            if (!LoadReferenceData())
            {
                ShowErrorMessage(ApplicationConstants.DATA_LOAD_ERROR);
                this.Enabled = false;
            }
        }
        
        /// <summary>
        /// Fires when the form is shown. Validate that the user is logged in.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnShown(EventArgs e)
        {
            // If nobody is logged in, close up shop
            if (LSTApplication.User == null)
            {
                this.Close();
            }
        }

        /// <summary>
        /// Loads data for all the dropdown reference lists
        /// </summary>
        private bool LoadReferenceData()
        {
            bool ok = true;
            try
            {
                // Companies
                List<StocksDataSet.CompanyRow> companies = (from company in businessLayer.GetCompanies()
                                          select company).ToList();

                this.cmbCompanyTicker.DataSource = companies;
                this.cmbCompanyTicker.DisplayMember = "CompName";
                this.cmbCompanyTicker.ValueMember = "CompCode";

                this.cmbTickerCompany.DataSource = companies;
                this.cmbTickerCompany.DisplayMember = "CompName";
                this.cmbTickerCompany.ValueMember = "CompCode";

                // SecTypes
                this.cmbSecType.DataSource = (from secType in businessLayer.GetSecurityTypes()
                                              select secType).ToList();
                this.cmbSecType.ValueMember = "TypCode";
                this.cmbSecType.DisplayMember = "SecurityType";

                // TradeTypes
                List<StocksDataSet.TradeTypesRow> tradeTypes = (from tradeType in businessLayer.GetTradeTypes()
                                           select tradeType).ToList();

                this.cmbTradeType.DataSource = tradeTypes;
                this.cmbTradeType.DisplayMember = "TradeType";
                this.cmbTradeType.ValueMember = "TradeType";

                this.cmbTransactionType.DataSource = tradeTypes;
                this.cmbTransactionType.DisplayMember = "TradeType";
                this.cmbTransactionType.ValueMember = "TradeType";

                // Securities
                List<string> securities = (from tickers in businessLayer.GetSecurities()
                                           select tickers.Ticker).ToList();
                this.cmbTickers.DataSource = securities;
                this.cmbResearchTicker.DataSource = securities;

            }
            catch (DataLoadException dlex)
            {
                ShowErrorMessage(dlex.Message);
                ok = false;
            }
            catch (DataUpdateException duex)
            {
                ShowErrorMessage(duex.Message);
                ok = false;
            }
            catch (Exception ex)
            {
                ShowErrorMessage(ApplicationConstants.UNHANDLED_EXCEPTION);
                ok = false;
            }
            return ok;
        }

        /// <summary>
        /// Button click event handler to allow the user to search for a ticker 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnTickerLookup_Click(object sender, EventArgs e)
        {            
            string compName = this.cmbTickerCompany.Text;
            StocksDataSet.FindTickerDataTable tbl = businessLayer.FindTicker(compName);
            if (tbl != null)
            {
                tbl.BeginLoadData();
                lstTickerResults.DataSource = tbl;
                lstTickerResults.DisplayMember = "Ticker";
                lstTickerResults.Visible = true;
                lblTickerResults.Visible = true;
            }
        }

        /// <summary>
        /// Button click event handler to add a security to the database
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSaveSecurity_Click(object sender, EventArgs e)
        {
            #region Gather parameters
            // get the parameters to use for the update
            string ticker = this.txtTicker.Text;
            string company = this.cmbCompanyTicker.SelectedValue.ToString();
            string type = this.cmbSecType.SelectedValue.ToString();
            #endregion

            #region Process parameters
            // Validate the parameters and show a message box if they entered 
            // invalid information
            if (string.IsNullOrEmpty(ticker) && ticker.Length <= ApplicationConstants.MAX_STRING_FIELD_SIZE)
            {
                ShowErrorMessage(ApplicationConstants.INVALID_TICKER_ERROR);
                return;
            }

            if (string.IsNullOrEmpty(company) && company.Length <= ApplicationConstants.MAX_STRING_FIELD_SIZE)
            {
                ShowErrorMessage(ApplicationConstants.INVALID_COMPANY_ERROR);
                return;
            }

            if (string.IsNullOrEmpty(type) && type.Length <= ApplicationConstants.MAX_STRING_FIELD_SIZE)
            {
                ShowErrorMessage(ApplicationConstants.INVALID_SECURITY_TYPE_ERROR);
                return;
            }
            #endregion

            #region Do the update
            // we have valid parameters, continue with the update
            try
            {
                if (this.businessLayer.AddTicker(ticker, company, type) < 0)
                {
                    ShowErrorMessage(ApplicationConstants.DATA_UPDATE_ERROR.Replace(ApplicationConstants.PLACEHOLDER, ticker));
                }
                else
                {
                    ShowSuccessMessage(ApplicationConstants.TICKER_ADDED_SUCCESS);
                    LoadReferenceData(); // update all the lists
                }
            }
            catch (DataUpdateException duex)
            {
                MessageBox.Show(duex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ApplicationConstants.UNHANDLED_EXCEPTION);
            }
            #endregion
        }

        /// <summary>
        /// Button click event handler to add a trade to the database
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnEnterTrade_Click(object sender, EventArgs e)
        {
            #region Gather parameters
            // get the parameters to use for the update
            string ticker = this.cmbTickers.Text;

            double price = -1;
            double.TryParse(this.txtPrice.Text, out price);

            double qty = -1;
            double.TryParse(this.txtQty.Text, out qty);

            string type = this.cmbTradeType.Text;
            #endregion

            #region Process parameters
            // Validate the parameters and show a message box if they entered 
            // invalid information
            if (string.IsNullOrEmpty(ticker) && ticker.Length <= ApplicationConstants.MAX_STRING_FIELD_SIZE)
            {
                ShowErrorMessage(ApplicationConstants.INVALID_TICKER_ERROR);
                return;
            }

            if (qty <= 0)
            {
                ShowErrorMessage(ApplicationConstants.INVALID_QUANTITY_ERROR);
                return;
            }

            if (price <= 0)
            {
                ShowErrorMessage(ApplicationConstants.INVALID_PRICE_ERROR);
                return;
            }

            if (string.IsNullOrEmpty(type) && type.Length <= ApplicationConstants.MAX_STRING_FIELD_SIZE)
            {
                ShowErrorMessage(ApplicationConstants.INVALID_TRADE_TYPE_ERROR);
                return;
            }
            #endregion

            #region Do the update
            // we have valid parameters, continue with the update
            try
            {
                if (this.businessLayer.AddTrade(type, ticker, qty, LSTApplication.User.AccountID, price, DateTime.Now) < 0)
                {
                    MessageBox.Show(ApplicationConstants.DATA_UPDATE_ERROR.Replace(ApplicationConstants.PLACEHOLDER, ticker));
                }
                else
                {
                    MessageBox.Show(ApplicationConstants.TRADE_ENTERED_SUCCESS, ApplicationConstants.MSGBOX_TITLE, MessageBoxButtons.OK);
                    ResetUI();
                }
            }
            catch (DataUpdateException duex)
            {
                ShowErrorMessage(duex.Message);
            }
            catch (Exception ex)
            {
                ShowErrorMessage(ApplicationConstants.UNHANDLED_EXCEPTION);
            }
            #endregion
        }

        /// <summary>
        /// Button click event handler to add a transaction to the database
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSaveTransaction_Click(object sender, EventArgs e)
        {
            #region Gather parameters
            // get the parameters to use for the update
            string ticker = this.cmbTickers.Text;

            double price = -1;
            double.TryParse(this.txtPrice.Text, out price);

            double qty = -1;
            double.TryParse(this.txtQty.Text, out qty);

            string type = this.cmbTradeType.Text;
            DateTime dt = new DateTime();
            DateTime.TryParse(this.txtTransactionDate.Text, out dt);
            #endregion

            #region Process parameters
            // Validate the parameters and show a message box if they entered 
            // invalid information
            if (string.IsNullOrEmpty(ticker) && ticker.Length <= ApplicationConstants.MAX_STRING_FIELD_SIZE)
            {
                ShowErrorMessage(ApplicationConstants.INVALID_TICKER_ERROR);
                return;
            }

            if (qty <= 0)
            {
                ShowErrorMessage(ApplicationConstants.INVALID_QUANTITY_ERROR);
                return;
            }

            if (price <= 0)
            {
                ShowErrorMessage(ApplicationConstants.INVALID_PRICE_ERROR);
                return;
            }

            if (string.IsNullOrEmpty(type) && type.Length <= ApplicationConstants.MAX_STRING_FIELD_SIZE)
            {
                ShowErrorMessage(ApplicationConstants.INVALID_TRADE_TYPE_ERROR);
                return;
            }
            #endregion

            #region Do the update
            // we have valid parameters, continue with the update
            try
            {
                if (this.businessLayer.AddTransaction(type, ticker, qty, LSTApplication.User.AccountID, price, dt) < 0)
                {
                    ShowErrorMessage(ApplicationConstants.DATA_UPDATE_ERROR.Replace(ApplicationConstants.PLACEHOLDER, ticker));
                }
                else
                {
                    ShowSuccessMessage(ApplicationConstants.TRANSACTION_ENTERED_SUCCESS);
                    LoadReferenceData();
                }
            }
            catch (DataUpdateException duex)
            {
                ShowErrorMessage(duex.Message);
            }
            catch (Exception ex)
            {
                ShowErrorMessage(ApplicationConstants.UNHANDLED_EXCEPTION);
            }
            #endregion
        }

        /// <summary>
        /// This method resets the UI after a successful operation.
        /// </summary>
        private void ResetUI()
        {
            foreach (TabPage page in tabMain.TabPages)
            {
                foreach (TextBox t in page.Controls.OfType<TextBox>())
                {
                    t.Text = "";
                }
                foreach (ComboBox c in page.Controls.OfType<ComboBox>())
                {
                    c.SelectedIndex = 0;
                }
            }
        }

        private void btnLookup_Click(object sender, EventArgs e)
        {
            try
            {
                string ticker = this.cmbResearchTicker.Text;
                string[] results = this.businessLayer.LoadSiteContents(ApplicationConstants.TICKER_RESEARCH_URL.Replace("SYMBOL", ticker));

                this.lblSymbol.Text = results[0].Replace("\"", string.Empty);
                this.lblLastPrice.Text = results[1].Replace("\"", string.Empty);
                this.lblDate.Text = results[2].Replace("\"", string.Empty);
                this.lblTime.Text = results[3].Replace("\"", string.Empty);
                this.lblChange.Text = results[4].Replace("\"", string.Empty);
                this.lblOpenPrice.Text = results[5].Replace("\"", string.Empty);
                this.lblDayHigh.Text = results[6].Replace("\"", string.Empty);
                this.lblDayLow.Text = results[7].Replace("\"", string.Empty);
                this.lblTradeVolume.Text = results[8].Replace("\"", string.Empty);
            }
            catch (Exception ex)
            {
                ShowErrorMessage(ApplicationConstants.NO_INTERNET_CONNECTION);
            }
        }

        private void btnClose_Click_1(object sender, EventArgs e)
        {
            this.Close();
        }


    }
}

